#ifndef __MY_UTIL__
#define __MY_UTIL__

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <memory>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <jsoncpp/json/json.h>

namespace vod
{
    // 判断文件是否存在
    // 获取文件大小（属性）
    // 向文件写入数据
    // 从文件读取数据
    // 针对目录文件多一个创建目录
    class FileUtil
    {
    public:
        FileUtil(const std::string name) : _name(name) {}

        // 判断文件是否存在
        bool Exists()
        {
            // access的F_OK专门用于检测文件是否存在--- 存在则返回0
            int ret = access(_name.c_str(), F_OK);
            if (ret != 0)
            {
                std::cout << "file is not exists" << std::endl;
                return false;
            }
            return true;
        }

        // 获取文件大小（属性）
        size_t Size()
        {
            if (!Exists())
            {
                return 0;
            }

            // stat接口用于获取文件属性，其中st_size就是文件大小成员
            struct stat st;
            if (stat(_name.c_str(), &st) != 0)
            {
                std::cout << "get file stat failed" << std::endl;
                return 0;
            }

            return st.st_size;
        }

        // 向文件写入数据
        bool GetContent(std::string *content)
        {
            std::ifstream ifs;
            ifs.open(_name, std::ios::binary);
            if (ifs.is_open() == false)
            {
                std::cout << "open file failed" << std::endl;
                return false;
            }

            int flen = this->Size();
            content->resize(flen);
            ifs.read(&(*content)[0], flen);
            if (ifs.good() == false)
            {
                std::cout << "read file content failed" << std::endl;
                ifs.close();
                return false;
            }

            ifs.close();
            return true;
        }

        // 从文件读取数据
        bool SetContent(const std::string &content)
        {
            std::ofstream ofs;
            ofs.open(_name, std::ios::binary);
            if (ofs.is_open() == false)
            {
                std::cout << "open file failed" << std::endl;
                return false;
            }
            ofs.write(content.c_str(), content.size());
            if (ofs.good() == false)
            {
                std::cout << "write file content failed" << std::endl;
                ofs.close();
                return false;
            }

            ofs.close();
            return true;
        }

        // 针对目录文件多一个创建目录
        bool CreateDirectory()
        {
            if (Exists())
            {
                return true;
            }

            mkdir(_name.c_str(), 0777);
            return true;
        }

    private:
        std::string _name; // 文件路径名称
    };

    // 实现序列化和反序列化
    class JsonUtil
    {
    public:
        static bool Serialize(const Json::Value &root, std::string *str)
        {
            Json::StreamWriterBuilder swb;
            swb.settings_["emitUTF8"] = true;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            std::stringstream ss;
            int ret = sw->write(root, &ss);
            if (ret != 0)
            {
                std::cout << "Serialize failed" << std::endl;
                return false;
            }
            *str = ss.str();
            return true;
        }

        static bool UnSerialize(const std::string &str, Json::Value *root)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            std::string err;
            bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), root, &err);
            if (!ret)
            {
                std::cout << "UnSerialize failed: " << err.c_str() << std::endl;
                return false;
            }

            return true;
        }
    };
}

#endif